package user

import (
	"context"
	"strings"
	"time"

	"mall/common/cryptx"
	"mall/common/globalkey"
	"mall/common/resultx"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	"github.com/zeromicro/go-zero/core/logx"
)

type RegisterLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterLogic {
	return &RegisterLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *RegisterLogic) Register(in *user.RegisterReq) (*user.BaseIDResp, error) {
	if in.AuthType == nil || len(strings.TrimSpace(*in.AuthType)) == 0 {
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	var userId uint64
	var err error
	switch strings.TrimSpace(*in.AuthType) {
	case globalkey.UserAuthTypeMobile:
		userId, err = l.systemRegister(in)
	case globalkey.UserAuthTypeEmail:
		userId, err = l.systemRegister(in)
	case globalkey.UserAuthTypeUsername:
		userId, err = l.systemRegister(in)
	default:
		return nil, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	if err != nil {
		return nil, err
	}

	return &user.BaseIDResp{
		Id: userId,
	}, nil
}

func (l *RegisterLogic) systemRegister(in *user.RegisterReq) (uint64, error) {
	if in.AuthKey == nil || len(strings.TrimSpace(*in.AuthKey)) == 0 {
		return 0, resultx.StatusError(resultx.REUQEST_PARAM_ERROR, "")
	}

	authKey := strings.TrimSpace(*in.AuthKey)

	// 查询用户是否存在
	filterMap := make(map[string]map[string][]any)
	switch strings.TrimSpace(*in.AuthType) {
	case globalkey.UserAuthTypeMobile:
		filterMap[model.UserColumns.UserMobile] = map[string][]any{
			"equalTo": []any{authKey},
		}
	case globalkey.UserAuthTypeEmail:
		filterMap[model.UserColumns.UserEmail] = map[string][]any{
			"equalTo": []any{authKey},
		}
	case globalkey.UserAuthTypeUsername:
		filterMap[model.UserColumns.UserLogin] = map[string][]any{
			"equalTo": []any{authKey},
		}
	}
	userList, _, err := l.svcCtx.CurrentUser.GetList(l.ctx, model.M{
		"pageSize": uint64(1),
		"select":   ",",
	}, -1, filterMap)
	if err != nil {
		return 0, err
	}

	if len(userList) > 0 {
		return 0, resultx.StatusError(resultx.USER_EXISTS, "")
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return 0, resultx.StatusError(resultx.DB_ERROR, "")
	}

	now := time.Now()
	user := &model.User{
		UserStatus: uint16(globalkey.StatusEnabled),
		CreatedAt:  now,
		UpdatedAt:  now,
	}
	userDetail := &model.UserDetail{}

	if in.Mobile != nil && len(strings.TrimSpace(*in.Mobile)) > 0 {
		user.UserMobile = strings.TrimSpace(*in.Mobile)
	}
	if in.Email != nil && len(strings.TrimSpace(*in.Email)) > 0 {
		user.UserEmail = strings.TrimSpace(*in.Email)
	}
	if in.Name != nil && len(strings.TrimSpace(*in.Name)) > 0 {
		user.UserLogin = strings.TrimSpace(*in.Name)
	}
	if in.Password != nil && len(strings.TrimSpace(*in.Password)) > 0 {
		salt, err := cryptx.GenerateRandomHexString(16)
		if err != nil {
			logx.Errorw("Register systemRegister GenerateRandomHexString err", logx.Field("detail", err.Error()))
			salt = l.svcCtx.Config.Mysql.Salt
		}

		user.Salt = salt
		user.UserPass = cryptx.EncryptPasswordWithSalt(strings.TrimSpace(*in.Password), salt)
	}

	err = l.svcCtx.CurrentUser.Insert(l.ctx, tx, user, &model.UserRel{
		Detail: userDetail,
	})
	if err != nil {
		tx.Rollback()
		return 0, resultx.StatusError(resultx.USER_REGISTER_FAILED, "")
	}

	tx.Commit()

	return user.ID, nil
}
